import { FarrisDesignBaseNestedComponent, FarrisDesignBaseComponent } from '@farris/designer-element';
import { BuilderHTMLElement } from '@farris/designer-element';
import { FormPropertyChangeObject } from '../../../../entity/property-change-entity';
import Sortable from 'sortablejs';
import { DesignerEnvType, FormBasicService, RefreshFormService, SchemaService } from '@farris/designer-services';
import { ComponentFactoryResolver, Injector } from '@angular/core';
import { BsModalService } from '@farris/ui-modal';
import { GridFieldEditorComponent } from '../../common/property/editor/grid-field-editor/grid-field-editor.component';
import { NotifyService } from '@farris/ui-notify';

export default class FdCollectionBaseComponent extends FarrisDesignBaseNestedComponent {
  envType: DesignerEnvType;

  triggerBelongedComponentToMoveWhenMoved = true;

  /** DataGrid所属的Component实例 */
  belongedCmpInstance: FarrisDesignBaseNestedComponent;

  constructor(component: any, options: any) {
    super(component, options);

    // 组件所属分类为“集合类”
    this.category = 'dataCollection';

    const serviceHost = this.options.designerHost;
    const formBasicService = serviceHost.getService('FormBasicService') as FormBasicService;
    if (formBasicService) {
      this.envType = formBasicService.envType;
    }
  }


  /**
   * 属性变更后事件：默认监听样式类属性变更，并触发模板重绘
   * @param changeObject 变更集
   * @param propertyIDs 需要额外监听的属性ID列表
   */
  onPropertyChanged(changeObject: FormPropertyChangeObject, propertyIDs?: string[]): void {
    let dynamicPropertyIDs = ['appearance.class', 'appearance.style', 'size.width', 'size.height', 'inlineStyle'];
    if (propertyIDs) {
      dynamicPropertyIDs = dynamicPropertyIDs.concat(propertyIDs);
    }

    const propertyPath = changeObject.propertyPath ? changeObject.propertyPath + '.' : '';
    if (dynamicPropertyIDs.includes(propertyPath + changeObject.propertyID)) {
      this.triggerRedraw();
    }

    if (changeObject.propertyID === 'fields') {
      const refreshService = this.options.designerHost.getService('RefreshFormService') as RefreshFormService;
      const cmpToRefresh = this.parent ? this.parent.component.id : this.component.id;
      refreshService.refreshFormDesigner.next(cmpToRefresh);
    }

  }

  canAccepts(sourceElement: BuilderHTMLElement, targetElement?: BuilderHTMLElement): boolean {
    const serviceHost = this.options.designerHost;
    const dragResolveService = serviceHost.getService('DragResolveService');
    const resolveContext = dragResolveService.getComponentResolveContext(sourceElement, this);


    // 接收实体树中拖拽来的字段，需要判断是否属于当前组件绑定的实体
    if (resolveContext.sourceType === 'field') {
      const schemaService = serviceHost.getService('SchemaService') as SchemaService;
      const fieldInfo = schemaService.getFieldByIDAndVMID(resolveContext.bindingTargetId, this.viewModelId);
      if (!fieldInfo || !fieldInfo.schemaField) {
        return false;
      } else {
        return true;
      }
    }
    // 接收工具箱中拖拽来的输入类控件
    if (resolveContext.sourceType === 'control') {
      return resolveContext.controlCategory === 'input';
    }
    return false;
  }

  /**
   * 注册列表头的拖拽，用于调整列顺序
   */
  registerGridFieldDnd() {
    const dragToolBarContainer = this.element.querySelector('.f-datagrid-header');
    if (dragToolBarContainer) {
      // tslint:disable-next-line:no-unused-expression
      new Sortable(dragToolBarContainer, {
        direction: 'horizontal',
        animation: 150,
        onEnd: (evt) => {
          this.dragGridFieldEnd(evt);
        }
      });
    }
  }
  /**
   * 调整列顺序后同步修改DOM结构
   */
  dragGridFieldEnd(e: any) {
    const oldIndex = e.oldIndex;
    const newIndex = e.newIndex;

    if (oldIndex !== newIndex) {
      const field = this.component.fields[oldIndex];
      this.component.fields.splice(oldIndex, 1);
      this.component.fields.splice(newIndex, 0, field);
    }

  }

  /**
   * 不允许单独删除集合类控件，若要删除需要定位到所属Component去删除
   */
  checkCanDeleteComponent(): boolean {
    return false;
  }

  /**
   * 是否支持移动取决于所属Component是否支持移动
   */
  checkCanMoveComponent(): boolean {
    this.belongedCmpInstance = this.getBelongedComponentInstance(this);
    return this.belongedCmpInstance.checkCanMoveComponent();
  }

  /**
   * 弹出字段维护窗口
   */
  showFieldManager() {

    // 动态创建相关的服务需要从designerHost中获取
    const serviceHost = this.options.designerHost;
    const resolver = serviceHost.getService('ComponentFactoryResolver') as ComponentFactoryResolver;
    const injector = serviceHost.getService('Injector') as Injector;
    const modalService = serviceHost.getService('ModalService') as BsModalService;
    const notifyService = injector.get(NotifyService) as NotifyService;

    const compFactory = resolver.resolveComponentFactory(GridFieldEditorComponent);
    const compRef = compFactory.create(injector);
    const modalConfig = {
      title: '维护显示列',
      width: 950,
      height: 600,
      showButtons: true,
      buttons: compRef.instance.modalFooter
    };

    compRef.instance.value = this.component.fields || [];
    compRef.instance.editorParams = {
      fieldEditable: this.component.fieldEditable,
      viewModelId: this.viewModelId,
      gridType: this.component.type,
      controlSource: this.component.controlSource
    };

    const modalPanel = modalService.show(compRef, modalConfig);
    compRef.instance.closeModal.subscribe(() => {
      modalPanel.close();
    });
    compRef.instance.submitModal.subscribe((data) => {
      this.component.fields = data.value;
      const refreshService = this.options.designerHost.getService('RefreshFormService') as RefreshFormService;
      // 因为dataGrid涉及到弹出编辑区域，这里不能只重构dataGrid
      const cmpToRefresh = this.parent ? this.parent.component.id : this.component.id;
      refreshService.refreshFormDesigner.next(cmpToRefresh);

      if (this.component.enableHeaderGroup) {
        notifyService.info('修改显示列后请重新配置多表头');
      }
      modalPanel.close();
    });

  }

  /**
   * 删除后事件，用于连带删除schema实体表的场景
   */
  onRemoveComponent(): void {
    const serviceHost = this.options.designerHost;
    const schemaService = serviceHost.getService('SchemaService') as SchemaService;

    schemaService.removeSchemaEntityByViewModelId(this.viewModelId)
  }

}
